<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<script>
    // https://www.cnblogs.com/yanghai/p/14093038.html
    // 异步操作“未完成”（pending）
    // 异步操作“已完成”（resolved，又称fulfilled）
    // 异步操作“失败”（rejected）
    //
    // 这三种的状态的变化途径只有两种。
    // 异步操作从“未完成”到“已完成”
    // 异步操作从“未完成”到“失败”。
    // 这种变化只能发生一次，一旦当前状态变为“已完成”或“失败”，就意味着不会再有新的状态变化了。因此，Promise对象的最终结果只有两种。
    //
    // 异步操作成功，Promise对象传回一个值，状态变为resolved。
    // 异步操作失败，Promise对象抛出一个错误，状态变为rejected。

    function SelfPromise(executor = (resolve, reject) => {
    }) {
        this.PromiseState = 'pending'
        this.thenCallback = null
        this.catchCallback = null
        this.finallyCallback = null
        this.successValue = null
        this.ErrorValue = null
        executor((value) => {
            if (this.PromiseState === 'rejected') return;
            this.successValue = value
            this.PromiseState = 'resolved'
            typeof this.thenCallback === "function" && this.thenCallback(value)
            typeof this.finallyCallback === "function" && this.finallyCallback()
        }, (errorValue) => {
            if (this.PromiseState === 'resolved') return;
            this.ErrorValue = errorValue
            this.PromiseState = 'rejected'
            typeof this.catchCallback === "function" && this.catchCallback(errorValue)
            typeof this.finallyCallback === "function" && this.finallyCallback()
        })
    }

    SelfPromise.prototype.then = function (callback) {
        console.log('line then');
        this.thenCallback = callback
        return this
    }

    SelfPromise.prototype.catch = function (callback) {
        this.catchCallback = callback
        return this
    }

    SelfPromise.prototype.finally = function (callback) {
        this.finallyCallback = callback
        return this
    }

    const _promise = new SelfPromise((resolve, reject) => {
        setTimeout(() => {
            reject({code: 400, data: {desc: 'Error!'}})
        }, 500)
        setTimeout(() => {
            resolve({code: 200, data: {desc: 'Hello world!'}})
        }, 1000)
    }).then(res => {
        console.log(res, 'line 54');
    }).catch(err => {
        console.error(err, 'line 65');
    }).finally(() => console.log('line 71'))

    console.log(_promise);
</script>

</body>
</html>
